using System;
using System.Collections.Generic;
using System.Text;
using surfInterop;
using System.Runtime.Remoting;
using System.Drawing;

namespace Blimpbots.Recognition
{
    public class SurfLocal : IDisposable
    {
        private static SurfLocal _instance = new SurfLocal();
        private surfInterop.SurfEngine surfEngine = null;

        private double _regionLeft;
        private double _regionTop;

        public static SurfLocal Instance
        {
            get{ return _instance; }
        }

        private SurfLocal()
        {
            surfEngine = new surfInterop.SurfEngine();
        }

        private bool _doubleImageSize = false;

        public bool DoubleImageSize { set { _doubleImageSize = value; } }

        public SurfKeypoint[] FindKeypoints(Bitmap img, Rectangle region, double blobThresh)
        {
            region = FixRectangle(region, img);
            GrayscaleImage grayImg = new GrayscaleImage(img, region);
            SurfKeypoint[] kpts = surfEngine.findKeypoints(grayImg.Scan0, grayImg.Width, grayImg.Height, blobThresh, _doubleImageSize);

            #region Move keypoints into the frame of the original image

            _regionLeft = (double)region.Left;
            _regionTop = (double)region.Top;

            for (int i = 0; i < kpts.Length; i++)
            {
                kpts[i].x += _regionLeft;
                kpts[i].y += _regionTop;
            }

            #endregion

            return kpts;
        }

        private Rectangle FixRectangle(Rectangle region, Bitmap bitmap)
        {
            int left = region.Left;
            int right = region.Right;
            int top = region.Top;
            int bottom = region.Bottom;

            if (left < 0) left = 0; else if (left >= bitmap.Width) left = bitmap.Width - 1;
            if (right < 0) right = 0; else if (right >= bitmap.Width) right = bitmap.Width - 1;
            if (top < 0) top = 0; else if (top >= bitmap.Height) top = bitmap.Height - 1;
            if (bottom < 0) bottom = 0; else if (bottom >= bitmap.Height) bottom = bitmap.Height - 1;

            region = new Rectangle(left, top, right - left, bottom - top);

            return region;
        }

        public SurfKeypoint[] DescribeKeypoints(int[] indices)
        {
            SurfKeypoint[] kpts =  surfEngine.describeKeypoints(indices);

            #region Move keypoints into the frame of the original image

            for (int i = 0; i < kpts.Length; i++)
            {
                kpts[i].x += _regionLeft;
                kpts[i].y += _regionTop;
            }

            #endregion

            return kpts;
        }

        public SurfKeypoint[] FindKeypoints(GrayscaleImage grayImg, double blobThresh)
        {
            return surfEngine.findKeypoints(grayImg.Scan0, grayImg.Width, grayImg.Height, blobThresh, _doubleImageSize);
        }

        #region IDisposable Members

        public void Dispose()
        {
            surfEngine.Dispose();
        }

        #endregion
    }
}
